Nuxt 中的 SSR 配置
本文记录了在 Nuxt 项目中排查和修复 PWA(Progressive Web App)注册失败问题的完整过程,涉及 Service Worker 注册、Vite PWA 插件配置以及离线缓存策略等内容。
问题背景
Nuxt 应用启用了 PWA 功能后,访问 localhost:3000 时发现:
- 页面右上角没有出现下载按钮
- 虽然 Chrome DevTools 的 Application 面板中能看到 Workbox,但 Service Worker 并未成功注册
问题排查
诊断 Service Worker 注册状态
在页面组件中通过 useNuxtApp() 获取 PWA 对象并打印状态:
<script setup>
const { $pwa } = useNuxtApp()
// 定时打印 PWA 状态,用于调试
setInterval(() => {
console.log('needRefresh:', $pwa.needRefresh)
console.log('offlineReady:', $pwa.offlineReady)
console.log('isInstalled:', $pwa.isInstalled)
console.log('showInstallPrompt:', $pwa.showInstallPrompt)
console.log('swActivated:', $pwa.swActivated)
}, 10000)
</script>
vue
如果所有状态持续为 false,说明 Service Worker 未成功注册。
根因分析
查阅 @vite-pwa/nuxt 源码和官方示例后发现:需要在 PWA 的 client 配置中启用 periodicSyncForUpdates,否则即使设置了 registerType: 'immediate',Service Worker 也无法完成注册和激活。
解决方案
1. 完善 Vite PWA 配置
在 nuxt.config.ts 中补充完整的 PWA 配置:
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@vite-pwa/nuxt'],
pwa: {
registerType: 'immediate',
client: {
// 关键配置:启用定期同步检查更新
periodicSyncForUpdates: 3600, // 生产环境建议 3600 秒(1 小时)
},
workbox: {
// 配置需要缓存的文件类型
globPatterns: [
'**/*.{js,css,html,png,jpg,svg,ico}',
],
},
},
})
typescript
配置说明:
| 配置项 | 说明 |
|---|---|
registerType: 'immediate' | 立即注册 Service Worker |
periodicSyncForUpdates | 定期检查更新的间隔(秒) |
globPatterns | Workbox 缓存匹配的文件模式 |
2. 添加 VitePwaManifest 组件
在根组件 app.vue 中添加 PWA 清单组件:
<!-- app.vue -->
<template>
<VitePwaManifest />
<NuxtPage />
</template>
vue
这是一个容易被忽略的步骤,缺少该组件会导致 PWA 清单无法正确注入。
3. 清理旧注册逻辑
配置完成后,原先在页面组件中手动编写的 Service Worker 注册逻辑可以移除:
<!-- 移除这些手动注册代码 -->
<!-- <script setup>
// setInterval 打印逻辑 - 不再需要
// 手动注册逻辑 - 不再需要
// install 事件监听 - 不再需要
</script> -->
vue
直接通过 nuxt.config.ts 的声明式配置管理 PWA,代码更简洁。
验证 Service Worker 注册成功
清理旧注册
- 打开 Chrome DevTools → Application → Service Workers
- 点击 Unregister 注销所有旧的 Service Worker
- 或者访问
chrome://serviceworker-internals/,搜索端口后批量 Stop and Unregister
确认注册成功
刷新页面后检查:
offlineReady: true ✅
swActivated: true ✅
text
测试离线功能
- 在 DevTools → Application → Service Workers 中勾选 Offline
- 刷新页面,应用应能正常访问(缓存的内容可用)
- 图片等动态接口数据在离线时不可用(因为接口无法请求)
缓存策略优化
调整缓存范围
可以通过 globPatterns 扩大缓存范围:
workbox: {
// 最激进的方式:缓存所有资源
globPatterns: ['**/*.*'],
}
typescript
注意:使用
**/*.*时需谨慎,大型资源文件(如 woff2 字体、大型 bundle)会导致缓存过程变慢。
首次访问的报错
Nuxt SSR 应用首次访问时,控制台可能出现类似 preserved URL 的报错。这是因为 Service Worker 在根路径下找不到预缓存的 index.html。该错误可以安全忽略,不影响功能。
生产环境部署建议
| 建议 | 说明 |
|---|---|
periodicSyncForUpdates | 设置为 3600(1 小时),避免频繁检查 |
globPatterns | 精确匹配需要的文件类型,不要使用 **/*.* |
| 缓存大文件 | 字体、大型 JS 文件需评估是否值得缓存 |
| 调试 Service Worker | 使用 Chrome 无痕模式,避免旧缓存干扰 |
总结
Nuxt 中 SSR + PWA 的完整配置流程:
- 在
nuxt.config.ts中配置@vite-pwa/nuxt模块 - 启用
client.periodicSyncForUpdates确保 SW 正常注册 - 在
app.vue中添加<VitePwaManifest />组件 - 移除手动注册逻辑,使用声明式配置
- 通过 DevTools 验证
offlineReady和swActivated状态
↑